package value

import (
	"context"
	"fmt"
	"github.com/spf13/cast"
	"tongquetai_server/activity_vk/domain/manage/common/static_data"
	value2 "tongquetai_server/activity_vk/domain/value"
	utils2 "tongquetai_server/activity_vk/infrastructure/utils"
)

const (
	SvrPackageAwardCountV2 = 1 // 现金礼包配置中的礼包名称,填充到服务端的数据相应的道具数量固定为1
	GoldCoin               = "金币"
	GoldCoinId             = "virtual_currency_1"
	Food                   = "食物"
	FoodId                 = "role_attr_4"
	Coupon                 = "点券"
	CouponId               = "activity_item_1052401"
	Cash                   = "现金"
	CashId                 = ""
)

var (
	SvrPackageStoreCouponItemV2 = SvrItem{GameObjectId: CouponId}   // 点券
	SvrPackageStoreGoldItemV2   = SvrItem{GameObjectId: GoldCoinId} // 金币
	SvrPackageStoreFoodItemV2   = SvrItem{GameObjectId: FoodId}     // 食物
	CurrencyMap                 = map[string]SvrItem{
		GoldCoin: SvrPackageStoreGoldItemV2,
		Coupon:   SvrPackageStoreCouponItemV2,
		Food:     SvrPackageStoreFoodItemV2,
		Cash:     {},
	}
	CurrencyIdMap = map[string]string{
		GoldCoinId: GoldCoin,
		FoodId:     Food,
		CouponId:   Coupon,
		CashId:     Cash,
	}
)

// @META.table:json
/*
[
    ["礼包配置"],
    ["礼包类型", "编号", "礼包名称", "货币种类", "货币数量", "购买项id", "价格", "第几天开始", "第几天结束", "开始时间", "结束时间", "价值千分比", "限购次数", "是否每日重置"],
    ["糖果屋", 1, "糖果屋1级礼包", "食物", 100, "", "", 1, 2, "00:00:00", "23:59:59", 28000, 1, "否"],
    ["糖果屋", 2, "糖果屋2级礼包", "金币", 50, "", "", 3, 4, "00:00:00", "23:59:59", 27000, 1, "否"]
]
*/

// @META.struct:tqt
type TqtPackageStoreV2 struct {
	TypName          string  `json:"typName" header:"礼包类型" allowEmpty:"true"`                        // 礼包类型名称
	Typ              int     `json:"typ" skipField:"true" validate:"gte=0"`                          // 礼包类型
	No               int     `json:"no" header:"编号" validate:"gt=0"`                                 // 编号
	PackageName      string  `json:"packageName" header:"礼包名称" validate:"required"`                  // 礼包名称
	Currency         string  `json:"currency" header:"货币种类" validate:"required"`                     // 货币种类
	CurrencyCount    int     `json:"currencyCount" header:"货币数量" allowEmpty:"true" validate:"gte=0"` // 货币数量
	LogicalProductId string  `json:"logicalProductId" header:"购买项id" allowEmpty:"true"`              // 购买项id
	Price            float64 `json:"price" header:"价格" allowEmpty:"true" validate:"gte=0"`           // 价格
	StartDay         int     `json:"startDay" header:"第几天开始" validate:"gt=0"`                        // *第几天结束和第几天开始的填写值需要>0； *第几天结束≥第几天开始(validate)
	EndDay           int     `json:"endDay" header:"第几天结束" validate:"gt=0"`                          // *第几天结束和第几天开始的填写值需要>0； *第几天结束≥第几天开始(validate)
	StartTime        TqtTime `json:"startTime" header:"开始时间" validate:"required"`                    // *开始时间和结束时间需填写时间格式：时：分：秒
	EndTime          TqtTime `json:"endTime" header:"结束时间" validate:"required"`                      // *开始时间和结束时间需填写时间格式：时：分：秒
	Value            int     `json:"value" header:"价值千分比" allowEmpty:"true" validate:"gte=0"`
	BuyLimit         int     `json:"buyLimit" header:"限购次数" validate:"gt=0"`
	IsDailyReset     bool    `json:"isDailyReset" header:"是否每日重置" true:"是" false:"否"`
}

func (t *TqtPackageStoreV2) Call(ctx context.Context) (err error) {
	if t.TypName == "" {
		return
	}
	// 校验礼包类型
	packageStoreItems, err := static_data.GetPackageStore().GetNameMap(ctx)
	if err != nil {
		return
	}
	if _, ok := packageStoreItems[t.TypName]; !ok {
		err = fmt.Errorf("礼包类型名称:[%s]只能填写礼包类型表中已有的数据", t.TypName)
		return
	}
	// 赋值
	t.Typ = packageStoreItems[t.TypName].No
	// 货币种类
	_, ok := CurrencyMap[t.Currency]
	if !ok {
		return fmt.Errorf("礼包配置:货币种类只能填写“食物”、“金币”、“点券”、“现金”")
	}

	return
}
// @META.struct:svr
type SvrPackageStoreV2 struct {
	No           int      `json:"no"`             // 编号
	Award        SvrAward `json:"award"`          // 商品，id填礼包的gId
	Price        SvrAward `json:"price"`          // 价格
	Typ          int      `json:"typ"`            // 类型 查询接口：https://xmdc.yuque.com/hgngvk/dvagbh/fryh5a8ahcniuihc#maQYW
	Value        int      `json:"value"`          // 价值千分比分子
	BuyLimit     int      `json:"buy_limit"`      // 限购，-1表示无限
	StartOffset  int      `json:"start_offset"`   // 开始时间，距活动开始时间毫秒数
	EndOffset    int      `json:"end_offset"`     // 结束时间，距活动开始时间毫秒数
	IsDailyReset bool     `json:"is_daily_reset"` // 是否每日重置
}

// ------------------------------------ 适配器部分 -----------------------------------

// ToTqtPackageStoreV2 服务端转铜雀台
func ToTqtPackageStoreV2(ctx context.Context, SvrPackageStoreV2 []SvrPackageStoreV2,
	actType int, useSystem string) (tqtPackageStore []TqtPackageStoreV2, err error) {
	// 礼包类型
	packageStoreTypMap, err := static_data.GetPackageStore().GetItemNoMap(ctx)
	if err != nil {
		return
	}
	// 购买项
	productIdMap, err := static_data.GetPayLogicalProduct().GetProductIdMap(ctx)
	if err != nil {
		return
	}
	// 礼包静态表
	packageGameObjectIdMap, err := static_data.GetGiftPackage(actType, useSystem).GetGameObjectIdMap(ctx)
	if err != nil {
		return
	}
	var (
		productItem      static_data.PayLogicalProduct
		logicalProductId string
		price            float64
		startTimeSeconds int
		startDay         int
		endDay           int
		startTime        TqtTime
		endTime          TqtTime
	)
	// 获取活动开始时间的偏移量
	startTimeSeconds, err = getActivityStartTimeToSecondsV2(ctx)
	if err != nil {
		return
	}
	tqtPackageStore = make([]TqtPackageStoreV2, 0, len(SvrPackageStoreV2))
	for _, item := range SvrPackageStoreV2 {
		// 购买项转换，“消耗点券数量” 和 "消耗金币数量"为0时，购买项必填
		logicalProductId = ""
		price = 0
		if item.Price.Count == 0 {
			productItem = getProductInfoV2(item.Award.GameObjectId, productIdMap, packageGameObjectIdMap)
			logicalProductId = productItem.Id
			price = productItem.Price
		}

		currency := CurrencyIdMap[item.Price.GameObjectId]
		currencyCount := item.Price.Count

		// 时间转换
		startDay, startTime = toTqtTimeV2(item.StartOffset, startTimeSeconds)
		endDay, endTime = toTqtTimeV2(item.EndOffset, startTimeSeconds)

		// 构造
		tqtPackageStore = append(tqtPackageStore, TqtPackageStoreV2{
			Typ:              item.Typ,
			TypName:          packageStoreTypMap[item.Typ].Name,
			No:               item.No,
			PackageName:      packageGameObjectIdMap[item.Award.GameObjectId].Name,
			Currency:         currency,
			CurrencyCount:    currencyCount,
			LogicalProductId: logicalProductId, // 购买项转换，“消耗点券数量”为0时，购买项必填
			Price:            price,            // 购买项转换，“消耗点券数量”为0时，购买项必填
			StartDay:         startDay,         // 第N天开始
			EndDay:           endDay,           // 第N天结束
			StartTime:        startTime,        // 活动开始时间
			EndTime:          endTime,          // 活动结束时间
			Value:            item.Value,
			BuyLimit:         item.BuyLimit,
			IsDailyReset:     item.IsDailyReset,
		})
	}
	return
}

// ToSvrPackageStoreV2 铜雀台转服务端
func ToSvrPackageStoreV2(ctx context.Context, TqtPackageStoreV2 []TqtPackageStoreV2,
	startTime string, actType int, useSystem string) (svrPackageStore []SvrPackageStoreV2, err error) {
	// 礼包静态表
	packageNameMap, err := static_data.GetGiftPackage(actType, useSystem).GetNameMap(ctx)
	if err != nil {
		return
	}
	// 初始化
	svrPackageStore = make([]SvrPackageStoreV2, 0, len(TqtPackageStoreV2))
	var (
		svrPriceAward SvrAward
		startOffset   int
		endOffset     int
	)
	for _, v := range TqtPackageStoreV2 {
		// 价格奖励，初始化 默认 现金传空
		svrPriceAward = SvrAward{}
		if v.Currency != Cash {
			svrPriceAward = SvrAward{
				SvrItem: CurrencyMap[v.Currency],
				Count:   v.CurrencyCount,
			}
		}

		// 时间偏移量
		startOffset, err = ToSvrTimeV2(v.StartDay, v.StartTime, startTime)
		if err != nil {
			return
		}
		endOffset, err = ToSvrTimeV2(v.EndDay, v.EndTime, startTime)
		if err != nil {
			return
		}

		// 构造
		svrPackageStore = append(svrPackageStore, SvrPackageStoreV2{
			No: v.No,
			Award: SvrAward{
				SvrItem: SvrItem{
					GameObjectId: packageNameMap[v.PackageName].GameObjectId,
				},
				Count: SvrPackageAwardCountV2, // 数量固定写死
			},
			Price:        svrPriceAward, // 道具对象
			Typ:          v.Typ,
			Value:        v.Value,
			BuyLimit:     v.BuyLimit,
			StartOffset:  startOffset,
			EndOffset:    endOffset,
			IsDailyReset: v.IsDailyReset,
		})
	}
	return
}

// 获取购买项，购买项没有礼包名称，需要通过礼包表获取
func getProductInfoV2(gameObjectId string, productIdMap map[string]static_data.PayLogicalProduct,
	packageIdItemMap map[string]static_data.PackageItem) (res static_data.PayLogicalProduct) {
	if gameObjectId == "" {
		return
	}
	// 获取礼包数据
	packageItem, ok := packageIdItemMap[gameObjectId]
	if !ok {
		return
	}
	// 获取购买项数据
	res = productIdMap[packageItem.LogicalProductId]
	return
}

/*
处理时间与偏移量
*/

// 获取活动开始时间距离0零0分0秒的秒数
func getActivityStartTimeToSecondsV2(ctx context.Context) (seconds int, err error) {
	queryConfigParams, ok := ctx.Value(value2.CtxQueryConfigParams).(value2.QueryConfigParams)
	if !ok {
		err = fmt.Errorf("CtxQueryConfigParams missing")
		return
	}
	seconds = queryConfigParams.StartTime.Second() + queryConfigParams.StartTime.Minute()*60 + queryConfigParams.StartTime.Hour()*3600
	return
}

func toTqtTimeV2(svrTime int, activityStartTimeSeconds int) (day int, timeStr TqtTime) {
	dayOffset, timeStrOffSet := utils2.SecondsToDayAndTimeStr(svrTime/1e3 + activityStartTimeSeconds)
	day = dayOffset + 1
	timeStr = TqtTime(timeStrOffSet)
	return
}

// 铜雀台转服务端 计算公式: [(第N天-1)*24*60*60+(开始时间-活动开始时间)]*1000(毫秒)
// 活动开始时间: activityStartTimeStr

func ToSvrTimeV2(day int, tqtTime TqtTime, activityStartTimeStr string) (svrTime int, err error) {
	secondOffset, err := utils2.CalOffsetSecondsByDayAndTimeStr(day-1, tqtTime.String(), activityStartTimeStr)
	if err != nil {
		return
	}
	svrTime = cast.ToInt(secondOffset * 1e3)
	return
}
